package main

import (
	fmt "fmt"
	"log"
	"math/rand"
	"sync"
	"time"
)

var wg sync.WaitGroup

func SayGreetings(greeting string, times int) {
	for i := 0; i < times; i++ {
		d := time.Second * time.Duration(rand.Intn(5)) / 2
		log.Println(greeting, i, d)
		time.Sleep(d) // 睡眠片刻（随机0到2.5秒）
	}
	//Done方法用来通知某个任务已经完成了。
	wg.Done() // 通知当前任务已经完成。
}

//每个go程序启动的时候只有一个对用户可见的协程，我们称之为主协程，一个协程可以开启更多其它新的协程。
//默认情况下，当主函数（主协程）退出后，子协程也随之结束，除非协程阻塞等待所有任务完成。
// 下面例子：我们想通过每个协程都打印10条问候语，但是主协程在子协程还没执行完成后就推出了，导致子协程提前game over。

// 和java和python的线程不同：主线程会等待子线程执行完毕后再退出。但是go的协程就需要使用并发同步技术来保证子协程执行完毕。

//rand.Seed(time.Now().UnixNano())
//log.SetFlags(0)
////Add方法用来注册新的需要完成的任务数。
//wg.Add(2) // 注册两个新任务
//go SayGreetings("AAAAAA---- ", 10)
//go SayGreetings("BB ", 10)
//wg.Wait() // 阻塞在这里，直到所有任务都已完成。

// deadLock
//wg.Add(1)
//go func() {
//	time.Sleep(time.Second * 2)
//	wg.Wait() // 阻塞在此
//}()
//wg.Wait() // 阻塞在此

//fmt.Println(runtime.NumCPU())
//fmt.Println(runtime.GOMAXPROCS(4))

func testBasicRoutine() {
	defer func() {
		fmt.Println("正常退出")
	}()
	fmt.Println("嗨！")
	defer func() {
		v := recover()
		fmt.Println("恐慌被恢复了：", v)
	}()

	// 运行时panic
	i := []int{1, 2, 3}
	fmt.Println(i[5])

	// 手动恐慌
	panic("恐慌了~~") // 产生一个恐慌
	fmt.Println("执行不到这里")
}

//嗨！
//恐慌被恢复了： runtime error: index out of range [5] with length 3
//正常退出
